<?php
/**
 * spRun  执行用户代码
 */
function psRun(){
	GLOBAL $__controller, $__action,$__version;
	log_d("Running with contoller $$__controller, action $__action and version $__version");

	// 对将要访问的控制器类进行实例化
	$handle_controller = loadClass($__controller, null,PS_PATH."/controller/$__version/".$__controller.".class.php");
	// 调用控制器出错将调用路由错误处理函数
	if(!is_object($handle_controller) || !method_exists($handle_controller, $__action)){
		dumpError('路由错误，请检查控制器目录下是否存在该控制器/动作。');
		exit;
	}
	// 路由并执行用户代码
	$handle_controller->$__action();
}

// /**
//  * dump  格式化输出变量程序
//  *
//  * @param vars    变量
//  * @param output    是否将内容输出
//  * @param show_trace    是否将使用dumpError对变量进行追踪输出
//  */
// function dump($vars, $output = TRUE, $show_trace = FALSE){
// 	// 部署模式下同时不允许查看调试信息的情况，直接退出。
// 	if(TRUE != SP_DEBUG && TRUE != $GLOBALS['PS_CONFIG']['allow_trace_onrelease'])return;
// 	if( TRUE == $show_trace ){ // 显示变量运行路径
// 		$content = dumpError(htmlspecialchars(print_r($vars, true)), TRUE, FALSE);
// 	}else{
// 		$content = "<div align=left><pre>\n" . htmlspecialchars(print_r($vars, true)) . "\n</pre></div>\n";
// 	}
//     if(TRUE != $output) { return $content; } // 直接返回，不输出。
//        echo "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body>{$content}</body></html>";
// 	   return;
// }

/**
 * import  载入包含文件
 *
 * @param filename    需要载入的文件名或者文件路径
 * @param auto_search    载入文件找不到时是否搜索系统路径或文件，搜索路径的顺序为：应用程序包含目录 -> 应用程序Model目录 -> sp框架包含文件目录
 * @param auto_error    自动提示扩展类载入出错信息
*/
function import($sfilename, $auto_search = TRUE){
	log_d("Try to import ".shortFileName($sfilename));
	if(isset($GLOBALS['PS_CONFIG']["import_file"][md5($sfilename)])){
		log_d(shortFileName($sfilename).' has imported, skip it!');
		return TRUE; // 已包含载入，返回
	}

	// 检查$sfilename是否直接可读
	if( TRUE == @is_readable($sfilename) ){
		require($sfilename); // 载入文件
		$GLOBALS['PS_CONFIG']['import_file'][md5($sfilename)] = TRUE; // 对该文件进行标识为已载入
		log_d("Imported ".shortFileName($sfilename)." in current dir.");
		return TRUE;
	}else{
		if(TRUE == $auto_search){ // 需要搜索文件

			foreach(array_merge($GLOBALS['PS_CONFIG']['ENV']['CLASS_PATH']) as $sp_include_path){
				if(false === strpos($sp_include_path, PS_PATH)) $sp_include_path = PS_PATH.'/'.$sp_include_path;
				// 检查当前搜索路径中，该文件是否已经载入
				if(isset($GLOBALS['PS_CONFIG']["import_file"][md5($sp_include_path.'/'.$sfilename)]))return TRUE;
				if( is_readable( $sp_include_path.'/'.$sfilename ) ){
					require($sp_include_path.'/'.$sfilename);// 载入文件
					$GLOBALS['PS_CONFIG']['import_file'][md5($sp_include_path.'/'.$sfilename)] = TRUE;// 对该文件进行标识为已载入
					//为了简化输出，将长路径替换成相对根目录的路径。
					log_d("Imported ".shortFileName("$sp_include_path/$sfilename"));
					return TRUE;
				}
			}
		}
	}
	dumpError("未能找到名为：{$sfilename}的文件");
	return FALSE;
}



/**
 * spClass  类实例化函数  自动载入类定义文件，实例化并返回对象句柄
 *
 * @param class_name    类名称
 * @param args   类初始化时使用的参数，数组形式
 * @param sdir 载入类定义文件的路径，可以是目录+文件名的方式，也可以单独是目录。sdir的值将传入import()进行载入
 * @param force_inst 是否强制重新实例化对象
 */
function loadClass($class_name, $args = null, $sdir = null, $force_inst = FALSE){
	log_d("Try to load class [$class_name] in dir or file [".shortFileName($sdir)."]");
	// 检查类名称是否正确，以保证类定义文件载入的安全性
	if(preg_match('/[^a-z0-9\-_.]/i', $class_name))dumpError($class_name."类名称错误，请检查。");
	// 检查是否该类已经实例化，直接返回已实例对象，避免再次实例化
	if(TRUE != $force_inst)if(isset($GLOBALS['PS_CONFIG']["inst_class"][$class_name]))return $GLOBALS['PS_CONFIG']["inst_class"][$class_name];
	// 如果$sdir不能读取，则测试是否仅路径
	if(null != $sdir
			&& !import($sdir)
			&& !import($sdir.'/'.$class_name.'.class.php'))
		return FALSE;

	$has_define = FALSE;
	// 检查类定义是否存在
	if(class_exists($class_name, false) || interface_exists($class_name, false)){
		$has_define = TRUE;
	}else{
		if( TRUE == import($class_name.'.class.php')){
			$has_define = TRUE;
		}
	}
	if(FALSE != $has_define){
		$argString = '';$comma = '';
		if(null != $args)for ($i = 0; $i < count($args); $i ++) {
			$argString .= $comma . "\$args[$i]"; $comma = ', ';
		}
		eval("\$GLOBALS['PS_CONFIG']['inst_class'][\$class_name]= new \$class_name($argString);");
		return $GLOBALS['PS_CONFIG']["inst_class"][$class_name];
	}
	dumpError($class_name."类定义不存在，请检查。");
}

/**
 * dumpError 框架定义的系统级错误提示
 *
 * @param msg    出错信息
 * @param output    是否输出
 * @param stop    是否停止程序
 */
function dumpError($msg, $output = TRUE, $stop = TRUE){
// 	if(TRUE != SP_DEBUG){
// 		error_log($msg);if(TRUE == $stop)exit;
// 	}
// 	$traces = debug_backtrace();
// 	$bufferabove = ob_get_clean();
// 	require_once 'notice.php';
// 	if(TRUE == $stop)exit;
}

function getArgs($name = null, $default = FALSE, $method = null)
{
	if(null != $name){
		if(hasArg($name) ){
			if( null != $method ){
				switch (strtolower($method)) {
					case 'get':
						return $_GET[$name];
					case 'post':
						return $_POST[$name];
					case 'cookie':
						return $_COOKIE[$name];
				}
			}
			if(isset($_GET[$name])){
				return $_GET[$name];
			}else if(isset($_POST[$name])){
				return $_POST[$name];
			}else if(isset($_COOKIE[$name])){
				return $_COOKIE[$name];
			}else{
				return $_REQUEST[$name];
			}
			
		}else{
			return (FALSE === $default) ? FALSE : $default;
		}
	}else{
		return $_REQUEST;
	}
}


function hasArg($name)
{
	return isset($_REQUEST[$name]);
}

function parseActionRequst(){
	$c=strtolower(getArgs('c','main'));
	$a=strtolower(getArgs('a','action'));
	$v=strtolower(getArgs('v',1));
	return array($c,$a,$v);
}

function log_i($msg){
	$log=Logger::singleton();
	$log->log_i($msg);
}
function log_d($msg){
	$log=Logger::singleton();
	$log->log_d($msg);
}
function log_w($msg){
	$log=Logger::singleton();
	$log->log_w($msg);
}
function log_e($msg){
	$log=Logger::singleton();
	$log->log_e($msg);
}

function log_sql($sql){
	$log=Logger::singleton();
	$log->log_sql("MySQL: [$sql]");
}
function shortFileName($absFileName,$justName=false){
	if($justName){
		return basename($absFileName);
	}else{
		return str_replace(PS_PATH, '',$absFileName);
	}
}

